// RemoteMapperDlg.cpp : implementation file
//

#include "stdafx.h"
#include "RemoteMapper.h"
#include "RemoteMapperDlg.h"
#include "ConfigurationUtil.h"
#include "GameSettingTypes.h"
#include "MSIDCfg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

using RemoteUtility::RemoteAdapter::IRemoteAdapter;

// CPCGameDialog dialog
static const CPoint keyBoxPos[] = {
	CPoint(353, 148-40),		// UP
	CPoint(353, 200-40),		// DOWN
	CPoint(135, 174-40),		// LEFT
	CPoint(353, 174-40),		// RIGHT
	CPoint(135, 213-40),		// OK
	CPoint(353, 234-40),		// HOME
	CPoint(353, 272-40),		// POWER
	CPoint(135, 332-40),		// []
	CPoint(353, 354-40),		// O
	CPoint(590, 182-40),		// TRIG
};
static const CPoint patBoxPos[] = {
	CPoint(579, 295),		// PATLEFT
	CPoint(579, 295+68),	// PATRIGHT
	CPoint(579, 295+68*2),	// PATUP
	CPoint(579, 295+68*3),	// PATDOWN
	CPoint(274, 415),		// PATTHRESH
	CPoint(348, 465),		// PATDITHER
};

static const char * const strMapConfigFile = "./cfgs/vr2map.cfg";
static const char * const strMSIDConfigFile = "./cfgs/vr2msid.cfg";
static const char * const strMacFilter = "00:12:6F";

static char * strRS232Msg[] = {
	"START",
	"CONTINUE",
	"END"
};
static const UINT uKeyMsg[] = {
	VK_F2,
	VK_F3,
	VK_F4
};

// CRemoteMapperDlg dialog
CRemoteMapperDlg::CRemoteMapperDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CRemoteMapperDlg::IDD, pParent)
	, m_trayIcon( IDR_MENU_TRAY )
	, m_pRemoteEmuManager( NULL )
	, m_remoteErrorCode( static_cast<RemoteUtility::RemoteAdapter::E_ZMotion_ErrorCode>(-1) )
{
	m_remoteAdapter = IRemoteAdapter::createRemoteAdapter(&m_msgShow);

	//set the parent dlg to edit control, for the message posting
	for ( int i = 0; i < E_KEYMAP_COUNT; i++ )
	{
		m_editKeyMap[i].setParentDlg(this);
	}
	for ( int i = 0; i < E_PATTERNMAP_COUNT; i++ )
	{
		m_editPatMap[i].setParentDlg(this);
	}

	m_pRemoteEmuManager = CRemoteEmuManager::getInstance();

	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

CRemoteMapperDlg::~CRemoteMapperDlg(){
	m_trayIcon.SetIcon(0);
	if ( m_hIcon )
	{
		DestroyIcon(m_hIcon);
		m_hIcon = NULL;
	}
	if( m_remoteAdapter ){
		delete m_remoteAdapter;
		m_remoteAdapter = NULL;
	}
	//	stopCheckEmulation();
	stopRemoteEmulation();

	if ( m_pRemoteEmuManager )
	{
		m_pRemoteEmuManager->setMessageBox( 0 );
		m_pRemoteEmuManager = NULL;
	}
}

void CRemoteMapperDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	for ( int i = 0; i < E_KEYMAP_COUNT; i++ )
	{
		DDX_Control( pDX, IDC_LEFTKEY + i, m_editKeyMap[i] );
	}
	for ( int i = 0; i < E_PATTERNMAP_COUNT; i++ )
	{
		DDX_Control( pDX, IDC_PAT_LEFT + i, m_editPatMap[i] );		
	}

	DDX_Control(pDX, IDC_BTN_START, m_btnStartSimulate);
	DDX_Control(pDX, IDC_BTN_STOP, m_btnStopSimulate);
	DDX_Control(pDX, IDC_BTN_CLOSE, m_btnClose);
}

BEGIN_MESSAGE_MAP(CRemoteMapperDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_CREATE()
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_MESSAGE(WM_KEYCODE_CHANGED, &CRemoteMapperDlg::OnKeyCodeChanged)

	// tray functions
	ON_MESSAGE(WM_MY_TRAY_NOTIFICATION, &CRemoteMapperDlg::OnTrayNotification)
	ON_MESSAGE(WM_RESTORE_FROM_TRAY, &CRemoteMapperDlg::OnRestoreFromTray)
	ON_COMMAND(ID_APP_SHOW, &CRemoteMapperDlg::OnAppShow)
	ON_COMMAND(ID_APP_EXIT, &CRemoteMapperDlg::OnAppExit)
	ON_MESSAGE(WM_SHOW_WINDOW, OnWindowShow)
	ON_MESSAGE(WM_HIDE_WINDOW, OnWindowHide)
	ON_MESSAGE(WM_REMOTENOTIFY_MSG, OnRemoteNotify)

	ON_BN_CLICKED(IDC_BTN_CLOSE, &CRemoteMapperDlg::OnBnClickedBtnClose)
	ON_BN_CLICKED(IDC_BTN_STOP, &CRemoteMapperDlg::OnBnClickedBtnStop)
	ON_BN_CLICKED(IDC_BTN_START, &CRemoteMapperDlg::OnBnClickedBtnStart)
END_MESSAGE_MAP()

// CRemoteMapperDlg message handlers

BOOL CRemoteMapperDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	m_pConfig = Utility::Configuration::CConfigurationUtil::GetInstance();

	//set text box font
	//set font to 32
	HFONT hFont = CreateFont (18, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, \
		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, \
		DEFAULT_PITCH | FF_SWISS, _T("Arial"));

	//move text box location
	CRect rcLabel;
	for ( int i = 0; i < E_KEYMAP_COUNT; i++ )
	{
		rcLabel.left = keyBoxPos[i].x;
		rcLabel.top = keyBoxPos[i].y + E_TITLEBAR_HEIGHT;
		rcLabel.right = rcLabel.left + 83;
		rcLabel.bottom = rcLabel.top + 19;
		m_editKeyMap[i].MoveWindow( &rcLabel );
		::SendMessage( m_editKeyMap[i].GetSafeHwnd(), WM_SETFONT, WPARAM(hFont), TRUE );
	}

	for ( int i = 0; i < E_PATTERNMAP_COUNT; i++ )
	{
		rcLabel.left = patBoxPos[i].x;
		rcLabel.top = patBoxPos[i].y + E_TITLEBAR_HEIGHT;
		rcLabel.right = rcLabel.left + 83;
		rcLabel.bottom = rcLabel.top + 19;
		m_editPatMap[i].MoveWindow( &rcLabel );
		::SendMessage( m_editPatMap[i].GetSafeHwnd(), WM_SETFONT, WPARAM(hFont), TRUE );
	}

	//load the previous configure
	loadPreviousConfigDescription(  strMapConfigFile, strMSIDConfigFile );

	initButton();

	//trayIcon init
	m_trayIcon.SetNotificationWnd(this, WM_MY_TRAY_NOTIFICATION);

	// prepare code page
	LCID curLcid = GetThreadLocale();
	const CRemoteMapperApp::TLocaleMap& rlcMap = static_cast<CRemoteMapperApp*>( AfxGetApp() )->getLocaleMap();
	CRemoteMapperApp::TLocaleMap::const_iterator citr = rlcMap.find( curLcid );
	UINT nCodePage = CP_ACP;
	if ( citr != rlcMap.end() )
	{
		nCodePage = (*citr).second;
	}
	else
	{
		nCodePage = 936;
	}
	//remote status
	CTextStatic::EFontFamily eff = CTextStatic::E_CHINESE_MSYH_FONT;
	CTextStatic::EFontStyle efs = CTextStatic::E_FONTSTYLE_BOLD;
	m_infoRemoteStatus.setFontSize( 14 );
	m_infoRemoteStatus.setCodePage( nCodePage );
	m_infoRemoteStatus.setFontFamily( eff );
	m_infoRemoteStatus.setFontStyle( efs );

	//move remote status label to propriety position
	rcLabel.left = 350;
	rcLabel.right = 800;
	rcLabel.top = 15;
	rcLabel.bottom = 45;
	m_infoRemoteStatus.MoveWindow(rcLabel);

	updateRemoteStatus();

	// prepare the emulation process
	startRemoteNotify();
	startCheckEmulation();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CRemoteMapperDlg::updateRemoteStatus()
{
	if (m_remoteErrorCode != m_remoteAdapter->getErrorCode())
	{
		m_remoteErrorCode = m_remoteAdapter->getErrorCode();
		CStringW strLabel;
		switch ( m_remoteErrorCode )
		{
		case RemoteUtility::RemoteAdapter::E_NOERROR:
			strLabel.LoadString( IDS_REMOTE_STATUSINFO );
			m_infoRemoteStatus.setFontColor( RGB(0, 255, 0) );
			m_btnStartSimulate.SetButtonEnable();
			break;
		case RemoteUtility::RemoteAdapter::E_USB_NOT_CONNECTED:
			strLabel.LoadString( IDS_REMOTE_STATUSNOUSB );
			m_infoRemoteStatus.setFontColor( RGB(255, 0, 0) );
			m_btnStopSimulate.SetButtonDisable();
			m_btnStartSimulate.SetButtonDisable();
			break;
		case RemoteUtility::RemoteAdapter::E_DRIVER_NOT_INSTALLED:
			strLabel.LoadString( IDS_REMOTE_STATUSNODRV );
			m_infoRemoteStatus.setFontColor( RGB(255, 0, 0) );
			m_btnStopSimulate.SetButtonDisable();
			m_btnStartSimulate.SetButtonDisable();
			break;
		default:
			break;
		}
		m_infoRemoteStatus.setLabelString( strLabel );

		// update rectangle area.
		CRect rc;
		m_infoRemoteStatus.GetWindowRect( &rc );
		ScreenToClient( &rc );
		InvalidateRect( &rc );
	}

}
bool CRemoteMapperDlg::testFocus() const
{
	HWND hWnd = ::GetForegroundWindow();
	HWND hMyWnd = AfxGetApp()->GetMainWnd()->GetSafeHwnd();
	if ( hWnd )
	{
		if ( hWnd == hMyWnd )
			return true;
		else
			return false;
	}
	else
		return false;
}

void CRemoteMapperDlg::initButton(){
	m_btnStartSimulate.MoveWindow(462, 498 + 40 + E_TITLEBAR_HEIGHT, 0, 0);
	m_btnStartSimulate.SetButtonImage(IDR_PNG_BTNSTARTGAME, _T("PNG"), RGB(255, 255, 255));

	m_btnStopSimulate.MoveWindow(582, 498 + 40 + E_TITLEBAR_HEIGHT, 0, 0);
	m_btnStopSimulate.SetButtonImage(IDR_PNG_BTNSTOPGAME, _T("PNG"), RGB(255, 255, 255));
	m_btnStopSimulate.SetButtonDisable();

	m_btnClose.MoveWindow(92, 498 + 40 + E_TITLEBAR_HEIGHT, 0, 0);
	m_btnClose.SetButtonImage(IDR_PNG_BTNCLOSE, _T("PNG"), RGB(255, 255, 255));

	if( m_remoteAdapter->getErrorCode() == RemoteUtility::RemoteAdapter::E_DRIVER_NOT_INSTALLED ||
		 m_remoteAdapter->getErrorCode() == RemoteUtility::RemoteAdapter::E_USB_NOT_CONNECTED
	){
		m_btnStartSimulate.SetButtonDisable();
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CRemoteMapperDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CRemoteMapperDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


int CRemoteMapperDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDialog::OnCreate(lpCreateStruct) == -1)
		return -1;

	//create remote status
	CRect rcLabel(0, 0, 0, 0);
	m_infoRemoteStatus.Create( _T("Static"), WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, rcLabel, this );

	//set window size
	CRect windowRect, clientRect;
	GetWindowRect( &windowRect );
	GetClientRect( &clientRect );
	windowRect.left = 0 + windowRect.left - clientRect.left;
	windowRect.top = 0 + windowRect.top - clientRect.top;
	windowRect.right = E_CLIENTAREA_WIDTH + windowRect.right - clientRect.right;
	windowRect.bottom = E_CLIENTAREA_HEIGHT + E_TITLEBAR_HEIGHT + windowRect.bottom - clientRect.bottom;
	MoveWindow( &windowRect );
	CenterWindow();

	//load background
	m_picGameInfo.Load( IDR_IMG_BACKGROUD, _T("PNG") );
	m_picBgBack.Load( IDR_IMG_BGBACKEND, _T("PNG") );
	m_picLogo.Load( IDR_PNG_LOGO, _T("PNG") );

	return 0;
}

BOOL CRemoteMapperDlg::OnEraseBkgnd(CDC* pDC)
{
	//main window background
	CRect tmprc;
	tmprc.top = 0;
	tmprc.left = 0;
	tmprc.right = tmprc.left + E_CLIENTAREA_WIDTH;
	tmprc.bottom = tmprc.top+E_CLIENTAREA_HEIGHT;
	m_picBgBack.Show(pDC, tmprc );
	m_picGameInfo.Show(pDC, tmprc );

	tmprc.top = 0;
	tmprc.left = 0;
	tmprc.right = tmprc.left + 204;
	tmprc.bottom = tmprc.top+50;
	m_picLogo.Show(pDC, tmprc );

	return TRUE;
}

void CRemoteMapperDlg::OnBnClickedBtnClose()
{
	OnBnClickedBtnStop();
	OnAppExit();
}

void CRemoteMapperDlg::OnBnClickedBtnStart()
{
	saveToFile( strMapConfigFile, strMSIDConfigFile );

	// load config file
	if ( m_pRemoteEmuManager )
	{
		m_pRemoteEmuManager->StopRemoteEmulation();
		m_pRemoteEmuManager->setRemoteMapCfg( strMapConfigFile );
		m_pRemoteEmuManager->setMSIDCfg( strMSIDConfigFile );
		m_pRemoteEmuManager->setMACFilter( strMacFilter );
	}

	//minimize to tray icon
	OnWindowHide( 0, 0 );
	
	// start emulation
	if ( m_pRemoteEmuManager )
	{
		m_pRemoteEmuManager->setFocusWnd( this );
		m_pRemoteEmuManager->setIndicateDown( TRUE );
		m_pRemoteEmuManager->StartRemoteEmulation();

		//button status change
		m_btnStartSimulate.SetButtonDisable();
		m_btnStopSimulate.SetButtonEnable();
	}
}


void CRemoteMapperDlg::OnBnClickedBtnStop()
{
	// stop emulation
	if ( m_pRemoteEmuManager )
	{
		m_pRemoteEmuManager->StopRemoteEmulation();
	}

	//button status change
	m_btnStopSimulate.SetButtonDisable();
	m_btnStartSimulate.SetButtonEnable();
}

void CRemoteMapperDlg::loadPreviousConfigDescription(LPCSTR strMapCfg, LPCSTR strMsidCfg){
	std::stringstream ss;
	ss.str("");

	// load MSID description
	CMSIDCfg msidCfg;
	RemoteUtility::LoadCfgFile( strMsidCfg, &msidCfg );
	// UP
	// DOWN
	// LEFT
	// RIGHT
	// OK
	// HOME
	// POWER
	// []
	// O
	// TRIG
	ss << MSID_REMOTE_SECTION_ << 0;
	const char* strMapDesc[] = {
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_UPDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_DOWNDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_LEFTDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_RIGHTDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_OKDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_HOMEDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_POWERDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_SQUAREDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_CIRCLEDESC, ss.str().c_str()),
		RemoteUtility::GetCfgVarStr(GAME_REMOTEMAP_TRIGDESC, ss.str().c_str()),
	};
	for (int j = 0; j < E_KEYMAP_COUNT; j++)
	{
		CA2CT pszDesc(strMapDesc[j]);
		m_editKeyMap[j].SetWindowText( pszDesc );
	}

	ss.str("");
	RemoteUtility::UnloadCfgFile();

	// load REMOTE description
	CRemoteMapCfg rmapCfg;
	GameUtility::LoadCfgFile( strMapCfg, &rmapCfg );
	// PATUP
	// PATDOWN
	// PATLEFT
	// PATRIGHT
	// PATTHRESH
	// PATDITHER
	ss.str("");
	ss << REMOTE_SECTION_ << 0;
	const char* strMapDesc2[] = {
		GameUtility::GetCfgVarStr(REMOTE_PATTERNMAP_LEFTDESC, ss.str().c_str()),
		GameUtility::GetCfgVarStr(REMOTE_PATTERNMAP_RIGHTDESC, ss.str().c_str()),
		GameUtility::GetCfgVarStr(REMOTE_PATTERNMAP_UPDESC, ss.str().c_str()),
		GameUtility::GetCfgVarStr(REMOTE_PATTERNMAP_DOWNDESC, ss.str().c_str()),
		GameUtility::GetCfgVarStr(REMOTE_PATTERNMAP_THRESHDESC, ss.str().c_str()),
		GameUtility::GetCfgVarStr(REMOTE_PATTERNMAP_DITHERDESC, ss.str().c_str()),
	};
	for (int j = 0; j < E_PATTERNMAP_COUNT; j++)
	{
		CA2CT pszDesc(strMapDesc2[j]);
		m_editPatMap[j].SetWindowText( pszDesc );
	}

	ss.str("");

	GameUtility::UnloadCfgFile();
}

void CRemoteMapperDlg::saveToFile( LPCSTR strMapCfg, LPCSTR strMsidCfg ){
	// load MSID description
	CMSIDCfg msidCfg;
	RemoteUtility::LoadCfgFile( strMsidCfg, &msidCfg );
	// UP
	// DOWN
	// LEFT
	// RIGHT
	// OK
	// HOME
	// POWER
	// []
	// O
	// TRIG
	CString strContent;
	m_editKeyMap[0].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_UPDESC, strContent.GetString(), MSID_REMOTE_SECTION_0);
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_UP, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[1].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_DOWNDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_DOWN, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[2].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_LEFTDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_LEFT, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[3].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_RIGHTDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_RIGHT, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[4].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_OKDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_OK, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[5].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_HOMEDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_HOME, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[6].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_POWERDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	//RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_POWER, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[7].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_SQUAREDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_SQUARE, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[8].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_CIRCLEDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_CIRCLE, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);
	m_editKeyMap[9].GetWindowText( strContent );
	RemoteUtility::SetCfgVarStr(GAME_REMOTEMAP_TRIGDESC, strContent.GetString(), MSID_REMOTE_SECTION_0 );
	RemoteUtility::SetCfgVarInt(GAME_REMOTEMAP_TRIG, m_pConfig->getKeyCodeNumber( strContent ), MSID_REMOTE_SECTION_0);

	RemoteUtility::UnloadCfgFile();

	// load REMOTE description
	CRemoteMapCfg rmapCfg;
	GameUtility::LoadCfgFile( strMapCfg, &rmapCfg );
	// PATUP
	// PATDOWN
	// PATLEFT
	// PATRIGHT
	// PATTHRESH
	// PATDITHER
	m_editPatMap[0].GetWindowText( strContent );
	GameUtility::SetCfgVarStr(REMOTE_PATTERNMAP_LEFTDESC, strContent.GetString(), REMOTE_SECTION_0 );
	GameUtility::SetCfgVarInt(REMOTE_PATTERNMAP_LEFT, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	m_editPatMap[1].GetWindowText( strContent );
	GameUtility::SetCfgVarStr(REMOTE_PATTERNMAP_RIGHTDESC, strContent.GetString(), REMOTE_SECTION_0 );
	GameUtility::SetCfgVarInt(REMOTE_PATTERNMAP_RIGHT, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	m_editPatMap[2].GetWindowText( strContent );
	GameUtility::SetCfgVarStr(REMOTE_PATTERNMAP_UPDESC, strContent.GetString(), REMOTE_SECTION_0 );
	GameUtility::SetCfgVarInt(REMOTE_PATTERNMAP_UP, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	m_editPatMap[3].GetWindowText( strContent );
	GameUtility::SetCfgVarStr(REMOTE_PATTERNMAP_DOWNDESC, strContent.GetString(), REMOTE_SECTION_0 );
	GameUtility::SetCfgVarInt(REMOTE_PATTERNMAP_DOWN, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	m_editPatMap[4].GetWindowText( strContent );
	GameUtility::SetCfgVarStr(REMOTE_PATTERNMAP_THRESHDESC, strContent.GetString(), REMOTE_SECTION_0 );
	GameUtility::SetCfgVarInt(REMOTE_THRESHMAP_0, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	GameUtility::SetCfgVarInt(REMOTE_THRESHMAP_1, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	GameUtility::SetCfgVarInt(REMOTE_THRESHMAP_2, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	GameUtility::SetCfgVarInt(REMOTE_THRESHMAP_3, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	m_editPatMap[5].GetWindowText( strContent );
	GameUtility::SetCfgVarStr(REMOTE_PATTERNMAP_DITHERDESC, strContent.GetString(), REMOTE_SECTION_0 );
	GameUtility::SetCfgVarInt(REMOTE_DITHERMAP_0, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	GameUtility::SetCfgVarInt(REMOTE_DITHERMAP_1, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	GameUtility::SetCfgVarInt(REMOTE_DITHERMAP_2, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);
	GameUtility::SetCfgVarInt(REMOTE_DITHERMAP_3, m_pConfig->getKeyCodeNumber( strContent ), REMOTE_SECTION_0);

	GameUtility::UnloadCfgFile();
}

CString CRemoteMapperDlg::mapKeyNumberToString(int key){
	return this->m_pConfig->getKeyCodeString(key);
}

int CRemoteMapperDlg::mapKeyStringToNumber(CString key){
	return this->m_pConfig->getKeyCodeNumber(key);
}

//process the WM_KEYCODE_CHANGED message from CMyEditCtrol
LRESULT CRemoteMapperDlg::OnKeyCodeChanged(WPARAM pa1, LPARAM pa2){
	return 0;
}

BOOL CRemoteMapperDlg::PreTranslateMessage(MSG* pMsg)
{
	static WPARAM vkValues[] = {
		VK_RETURN,
		VK_ESCAPE,
		VK_LEFT,
		VK_RIGHT
	};
	if (pMsg->message == WM_MOUSEMOVE)
	{
		OnMouseEvent();
	}
	for ( int i = 0; i < E_KEYEVENT_COUNT; i++ )
	{
		// key down
		if ( !m_keyBits.test(i) && pMsg->message == WM_KEYDOWN
			&& pMsg->wParam == vkValues[i] )
		{
			m_keyBits.set(i);
			OnKeyEvent( static_cast<EKeyeventType>(i), TRUE );
		}

		// key up
		if ( m_keyBits.test(i) && pMsg->message == WM_KEYUP
			&& pMsg->wParam == vkValues[i] )
		{
			m_keyBits.reset(i);
			OnKeyEvent( static_cast<EKeyeventType>(i), FALSE );
		}
	}

	if (pMsg->message == WM_KEYDOWN)
	{
		if( pMsg->wParam == VK_RETURN 
			||  pMsg->wParam == VK_ESCAPE){
				//does not quit the dialog
				return TRUE;
		}
	}

	return CDialog::PreTranslateMessage(pMsg);
}

void CRemoteMapperDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CDialog::OnLButtonDown(nFlags, point);
	// Drag Window
	PostMessage( WM_NCLBUTTONDOWN , HTCAPTION, MAKELPARAM(point.x, point.y) );
}

void CRemoteMapperDlg::OnKeyEvent( EKeyeventType ekt, BOOL bDown )
{
}

void CRemoteMapperDlg::OnMouseEvent()
{
}

//////////////////////////////////////////////////////////////////////////
// tray functions
LRESULT CRemoteMapperDlg::OnTrayNotification( WPARAM uID, LPARAM lEvent )
{
	// let tray icon do default stuff
	return m_trayIcon.OnTrayNotification(uID, lEvent);
}

LRESULT CRemoteMapperDlg::OnRestoreFromTray( WPARAM uID, LPARAM lEvent )
{
	m_trayIcon.SetIcon( 0 );

	//just show the window, bring it to top
	if(this->IsIconic())
	{
		this->ShowWindow(SW_RESTORE);
	}
	else if(this->IsWindowVisible())
	{
		this->SetForegroundWindow();
	}
	else
	{
		this->ShowWindow(SW_SHOW);
	}

	return 0;
}

void CRemoteMapperDlg::OnAppShow()
{
	// TODO: Add your command handler code here
	if ( this->IsWindowVisible() )
	{
		//		m_trayIcon.SetIcon( IDI_ICON_PINGPONG );
		//		m_trayIcon.SetIcon( IDR_MAINFRAME );
		//		ShowWindow( SW_HIDE );
		OnWindowHide(0, 0);
	}
	else
	{
		//		m_trayIcon.SetIcon( 0 );
		//		ShowWindow( SW_SHOW );
		OnWindowShow(0, 0);
	}
}

//add 
void CRemoteMapperDlg::OnAppExit()
{
	DestroyWindow();
	AfxGetApp()->PostThreadMessage( WM_QUIT, 0, 0 );
}

LRESULT CRemoteMapperDlg::OnWindowShow( WPARAM wParam, LPARAM lParam )
{
	m_trayIcon.SetIcon( 0 );
	ShowWindow( SW_SHOW );
	CenterWindow();
	SetForegroundWindow();
	return 0;
}

LRESULT CRemoteMapperDlg::OnWindowHide( WPARAM wParam, LPARAM lParam )
{
	if (m_hIcon)
	{
		m_trayIcon.SetIcon(m_hIcon, NULL);
	}
	else
	{
		m_trayIcon.SetIcon( IDR_MAINFRAME );
	}
	//show ballon tips
	CString title;
	title.LoadString( IDS_BALLON_TITLE );
	m_trayIcon.ShowBalloonTip( IDS_BALLON_MSG, title.GetString(), 1000, NIF_TIP );

	ShowWindow( SW_HIDE );
	return 0;
}
// tray functions end
//////////////////////////////////////////////////////////////////////////

void CRemoteMapperDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	// TODO: Add your message handler code here and/or call default
	switch ( nID )
	{
	case SC_CLOSE:
		OnAppExit();
		break;
	case SC_MINIMIZE:
		OnWindowHide( 0, 0 );
		break;
	default:
		CDialog::OnSysCommand(nID, lParam);
		break;
	}
}

//dynamically check remote status
void CRemoteMapperDlg::startRemoteNotify()
{
	if ( m_pRemoteEmuManager
		/*&& 	m_remoteAdapter->getErrorCode() != RemoteUtility::RemoteAdapter::E_DRIVER_NOT_INSTALLED*/ )
	{
		//m_pRemoteEmuManager->StopRemoteEmulation();
		m_pRemoteEmuManager->setFocusWnd( this );
		m_pRemoteEmuManager->setIndicateDown( false );
		m_pRemoteEmuManager->setAutoReconnect( true );
		m_pRemoteEmuManager->setNotifyWnd(GetSafeHwnd());
		m_pRemoteEmuManager->setNotifyMsg(WM_REMOTENOTIFY_MSG);
		m_pRemoteEmuManager->setNotifyCode(0, E_NOTIFYCODE_NOERROR);
		m_pRemoteEmuManager->setNotifyCode(1, E_NOTIFYCODE_BROKEN);
		m_pRemoteEmuManager->setDisableMouseOnExit(true);
		size_t nCount = sizeof(strMapConfigFile) / sizeof(TCHAR*);

		m_pRemoteEmuManager->setMACFilter(strMacFilter);
		m_pRemoteEmuManager->setRemoteMapCfg( strMapConfigFile);
		m_pRemoteEmuManager->setMSIDCfg( strMSIDConfigFile );
		m_pRemoteEmuManager->StartRemoteEmulation();
	}
}
void CRemoteMapperDlg::stopRemoteEmulation()
{
	// affected by the motion control bit
	if ( m_pRemoteEmuManager )
	{
		m_pRemoteEmuManager->StopRemoteEmulation();
	}
}
void CRemoteMapperDlg::startCheckEmulation()
{
	if ( m_pRemoteEmuManager )
	{
#if defined(DEBUG) || defined(_DEBUG)
		m_pRemoteEmuManager->setCheckNotifyWnd(GetSafeHwnd());
		m_pRemoteEmuManager->setCheckNotifyMsg(WM_REMOTENOTIFY_MSG);
		m_pRemoteEmuManager->setCheckNotifyCode(VK_F5, E_NOTIFYCODE_F2PRESSED);
		m_pRemoteEmuManager->setCheckNotifyCode(VK_F6, E_NOTIFYCODE_F3PRESSED);
		m_pRemoteEmuManager->setCheckNotifyCode(VK_F7, E_NOTIFYCODE_F4PRESSED);
		m_pRemoteEmuManager->StartCheckEmulation();
#endif
	}
}
void CRemoteMapperDlg::stopCheckEmulation()
{
	if ( m_pRemoteEmuManager )
	{
#if defined(DEBUG) || defined(_DEBUG)
		m_pRemoteEmuManager->StopCheckEmulation();
#endif
	}
}

LRESULT CRemoteMapperDlg::OnRemoteNotify( WPARAM wParam, LPARAM lParam )
{
	using RemoteUtility::RemoteAdapter::E_NOERROR;
	using RemoteUtility::RemoteAdapter::E_USB_NOT_CONNECTED;
	COPYDATASTRUCT cds;
	std::string strmsg;
	switch (wParam)
	{
	case E_NOTIFYCODE_NOERROR:
		m_remoteAdapter->setErrorCode(E_NOERROR);
		break;
	case E_NOTIFYCODE_BROKEN:
		if (m_remoteAdapter->getErrorCode() != RemoteUtility::RemoteAdapter::E_DRIVER_NOT_INSTALLED)
			m_remoteAdapter->setErrorCode( RemoteUtility::RemoteAdapter::E_USB_NOT_CONNECTED );
		break;
	case E_NOTIFYCODE_F2PRESSED:
		cds.dwData = 0;
		strmsg = strRS232Msg[0];
		cds.cbData = strmsg.size();
		cds.lpData = (LPVOID)(strmsg.c_str());
		SendMessage(WM_COPYDATA, (WPARAM)GetSafeHwnd(), (LPARAM)(&cds));
		break;
	case E_NOTIFYCODE_F3PRESSED:
		cds.dwData = 0;
		strmsg = strRS232Msg[1];
		cds.cbData = strmsg.size();
		cds.lpData = (LPVOID)(strmsg.c_str());
		SendMessage(WM_COPYDATA, (WPARAM)GetSafeHwnd(), (LPARAM)(&cds));
		break;
	case E_NOTIFYCODE_F4PRESSED:
		cds.dwData = 0;
		strmsg = strRS232Msg[2];
		cds.cbData = strmsg.size();
		cds.lpData = (LPVOID)(strmsg.c_str());
		SendMessage(WM_COPYDATA, (WPARAM)GetSafeHwnd(), (LPARAM)(&cds));
		break;
	default:
		break;
	}
	updateRemoteStatus();

	return 0;
}
